﻿using System.Linq;
using ORM_Micro.SQLServerCE;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using ORM_Micro.Test.Models;
using ORM_Micro.Test.Properties;

namespace ORM_Micro.Test
{
    /// <summary>
    ///Classe de test pour DataContextTest, destinée à contenir tous
    ///les tests unitaires DataContextTest
    /// </summary>
    [TestClass()]
    public class DataContextTest
    {
        private TestContext testContextInstance;
        private string _connectionString;

        /// <summary>
        ///Obtient ou définit le contexte de test qui fournit
        ///des informations sur la série de tests active ainsi que ses fonctionnalités.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Attributs de tests supplémentaires
        // 
        //Vous pouvez utiliser les attributs supplémentaires suivants lorsque vous écrivez vos tests :
        //
        //Utilisez ClassInitialize pour exécuter du code avant d'exécuter le premier test dans la classe
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Utilisez ClassCleanup pour exécuter du code après que tous les tests ont été exécutés dans une classe
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Utilisez TestInitialize pour exécuter du code avant d'exécuter chaque test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            _connectionString = Settings.Default.SQLServerCEConnectionString;
        }
        //
        //Utilisez TestCleanup pour exécuter du code après que chaque test a été exécuté
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region Create Tests

        /// <summary>
        /// CreateLanguage Test without parameters
        /// </summary>
        [TestMethod()]
        public void CreateLanguageTest1()
        {
            const string createStatement = @"
                insert into Language(LanName, LanCulture)
                values('Français', 'fr-FR')";

            object lanId;

            using (var context = new DataContext(_connectionString))
            {
                context.CreateEntity(createStatement, out lanId);
            }
        }

        /// <summary>
        /// Create Language Test with simple parameters
        /// </summary>
        [TestMethod()]
        public void CreateLanguageTest2()
        {
            const string createStatement = @"
                insert into Language(LanName, LanCulture)
                values(@LanName, @LanCulture)";

            object lanId;

            using (var context = new DataContext(_connectionString))
            {
                context.DataContextBag.LanName = "English";
                context.DataContextBag.LanCulture = "en-EN";
                context.CreateEntity(createStatement, out lanId);
            }
        }

        /// <summary>
        /// Create Language Test with object parameters
        /// </summary>
        [TestMethod()]
        public void CreateLanguageTest3()
        {
            var language = new LanguageModel {Name = "Deutsch", Culture = "de-DE"};

            const string createStatement = @"
                insert into Language(LanName, LanCulture)
                values(@Language.Name, @Language.Culture)";

            object lanId;

            using (var context = new DataContext(_connectionString))
            {
                context.DataContextBag.Language = language;
                context.CreateEntity(createStatement, out lanId);
            }
        }

        /// <summary>
        /// Create User Test with object parameters
        /// </summary>
        [TestMethod()]
        public void CreateUserTest()
        {
            var user = new UserModel { Name = "John Smith", Address = "135 Street Avenue, City, State", BirthDate = new DateTime(1950, 1, 1), Money = 12056.25 };
            
            const string createStatement = @"
                insert into [User](UserFirstName, UserLastName, UserAddress, UserBirthDate, UserAccountMoney)
                values(@FirstName, @LastName, @User.Address, @User.BirthDate, @User.Money)";

            object userId;

            using (var context = new DataContext(_connectionString))
            {
                context.DataContextBag.FirstName = "John";
                context.DataContextBag.LastName = "Smith";
                context.DataContextBag.User = user;
                context.CreateEntity(createStatement, out userId);
            }

            Assert.IsNotNull(userId, "La clé userId renvoyée par la méthode est nulle");
            Assert.IsInstanceOfType(userId, typeof(decimal), "La clé userId renvoyée par la méthode n'est pas de type decimal");
        }

        #endregion

        #region Read Tests

        /// <summary>
        /// ReadLanguages Test without parameters
        /// </summary>
        [TestMethod()]
        public void ReadLanguagesTest()
        {
            List<LanguageModel> languages;

            const string readStatement = @"
                select  LanName as Name,
                        LanCulture as Culture
                from Language";

            using (var context = new DataContext(_connectionString))
            {
                languages = context.ReadEntities<LanguageModel>(readStatement).ToList();
            }

            Assert.IsInstanceOfType(languages, typeof(List<LanguageModel>), "La valeur renvoyée par la méthode n'est pas de type List<Language>");
            Assert.IsNotNull(languages, "La valeur renvoyée par la méthode est nulle");
            Assert.IsTrue(languages.Any(), "La valeur renvoyée contient 0 ligne");
        }

        /// <summary>
        /// ReadLanguage Test with parameters
        /// </summary>
        [TestMethod()]
        public void ReadLanguageTest()
        {
            LanguageModel language;

            const string readStatement = @"
                select  LanName as Name,
                        LanCulture as Culture
                from Language
                where LanCulture = @LanCulture";

            using (var context = new DataContext(_connectionString))
            {
                context.DataContextBag.LanCulture = "fr-FR";
                language = context.ReadEntity<LanguageModel>(readStatement);
            }

            Assert.IsInstanceOfType(language, typeof(LanguageModel), "La valeur renvoyée par la méthode n'est pas de type Language");
            Assert.IsNotNull(language, "La valeur renvoyée par la méthode est nulle");
        }

        #endregion

        #region Specific Tests

        /// <summary>
        /// SpecificTest With multiple parameters
        /// </summary>
        [TestMethod()]
        public void SpecificTest()
        {
            // Commande SQL
            var pagedResourcesQuery =
                @"
                WITH OrderedRequest AS
                (
	                select ROW_NUMBER() OVER (order by RessCode) - 1 as RowNumber,
		                ressId,
		                ressCode
	                from Ressources (nolock)
                )
                select	ord.ressId as ResourceId,
                        ord.ressCode as ResourceCode,
                        l.lanId as LanguageId,
                        rl.reslLabel as ResourceSentence
                from OrderedRequest ord
                inner join ressourcesLanguages rl (nolock)
                    inner join languages l (nolock)
                        on rl.lanId = l.lanId
                            and l.lanCulture = @CultureCode
                    on ord.ressId = rl.ressId
                inner join ApplicationsRessources apr
                    inner join Applications ap
                        on ap.appId = apr.appId
                            and ap.appName = @ApplicationName
                    on apr.ressId = ord.ressId                
                inner join OrderedRequest ord2
                    on ord2.ressCode = @ResourceCode
                where ord.RowNumber BETWEEN FLOOR(ord2.RowNumber/@PageSize) * @PageSize AND (FLOOR(ord2.RowNumber/@PageSize) * @PageSize) + (@PageSize - 1)";

            //On utilise la chaîne de connexion au portail
            using (var context = new DataContext(_connectionString))
            {
                context.DataContextBag.CultureCode = "fr-FR";
                context.DataContextBag.ApplicationName = "SEL";
                context.DataContextBag.ResourceCode = "ResBlaBla";
                context.DataContextBag.PageSize = 50;
                context.ReadEntities<object>(pagedResourcesQuery).ToList();
            }
        }

        #endregion
    }
}
